#include "stdafx.h"
#include "sobel.h"
#include "imageIterator.h"
#include "cv.h"
#include <omp.h>
#include <iostream>


void Sobel::process(IplImage *image) {


// 	IplImageIterator<unsigned char> 
// 		src(image,1,1,image->width-2,image->height-2);
// 	IplImageIterator<unsigned char> 
// 		res(output,1,1,image->width-2,image->height-2);
// 
// 	int sobel;
// 	while (!src) {
// 
// 		sobel= abs(src.neighbor(-1,-1) -  src.neighbor(1,-1) +
// 			2*src.neighbor(-1,0) - 2*src.neighbor(1,0) +
// 			src.neighbor(-1,1) -   src.neighbor(1,1)
// 			);
// 
// 		sobel+=abs(src.neighbor(-1,-1) -  src.neighbor(-1,1) +
// 			2*src.neighbor(0,-1) - 2*src.neighbor(0,1) +
// 			src.neighbor(1,-1) -   src.neighbor(1,1)
// 			);
// 
// 		*res= sobel > 255 ? 255 : sobel;
// 
// 		++src;
// 		++res;
// 	}

	int height = image->height;
	int width = image->width;
	int widthStep1 = image->widthStep;
	int widthStep2 = output->widthStep;
	uchar *data1 = (uchar*)image->imageData;
	uchar *data2 = (uchar*)output->imageData;
	int nch = image->nChannels;
	int y=0;
	int x=0;

	for( y=1; y<height-1; y++ )
	{
		uchar* image_ptr = data1 + y * widthStep1;
		uchar* output_ptr = data2+ y * widthStep2;
		for( x=1; x<widthStep1-1; x++ )
		{
			
			int sobel= abs(neighbor(image_ptr,x,-1,-1,widthStep1,nch) -  neighbor(image_ptr,x,1,-1,widthStep1,nch) +
				2*neighbor(image_ptr,x,-1,0,widthStep1,nch) - 2*neighbor(image_ptr,x,1,0,widthStep1,nch) +
				neighbor(image_ptr,x,-1,1,widthStep1,nch) -   neighbor(image_ptr,x,1,1,widthStep1,nch)
				);

			sobel+=abs(neighbor(image_ptr,x,-1,-1,widthStep1,nch) -  neighbor(image_ptr,x,-1,1,widthStep1,nch) +
				2*neighbor(image_ptr,x,0,-1,widthStep1,nch) - 2*neighbor(image_ptr,x,0,1,widthStep1,nch) +
				neighbor(image_ptr,x,1,-1,widthStep1,nch) -   neighbor(image_ptr,x,1,1,widthStep1,nch)
				);

			output_ptr[x] = sobel > 255 ? 255 : sobel;;          
		}
	} 



	
}

void Sobel::processOpenMP(IplImage *image) {

// 	IplImageIterator<unsigned char> 
// 		src(image,1,1,image->width-2,image->height-2);
// 	
// 	IplImageIterator<unsigned char> 
// 		res(output,1,1,image->width-2,image->height-2);
// 	//int sobel=0;
// 	#pragma omp parallel
// 	{
// 		#pragma omp single
// 		{			
// 			while (!src) {
// 				#pragma omp task firstprivate(src,res)
// 				{
// 					int sobel= abs(src.neighbor(-1,-1) -  src.neighbor(1,-1) +
// 						2*src.neighbor(-1,0) - 2*src.neighbor(1,0) +
// 						src.neighbor(-1,1) -   src.neighbor(1,1)
// 						);
// 
// 					sobel+=abs(src.neighbor(-1,-1) -  src.neighbor(-1,1) +
// 						2*src.neighbor(0,-1) - 2*src.neighbor(0,1) +
// 						src.neighbor(1,-1) -   src.neighbor(1,1)
// 						);
// 	
// 
// 					*res= sobel > 255 ? 255 : sobel;
// 										
// 					
// 				}		
// 				++res;
// 				
// 				++src;
// 				
// 			}
// 		}
// 	}
	
	int height = image->height;
	int width = image->width;
	int widthStep1 = image->widthStep;
	int widthStep2 = output->widthStep;
	uchar *data1 = (uchar*)image->imageData;
	uchar *data2 = (uchar*)output->imageData;
	int nch = image->nChannels;
	int y=0;
	int x=0;
#pragma omp parallel default(none)\
	shared(data1,data2,height,width,widthStep1,widthStep2,nch) private(y,x)
	{
#pragma omp for nowait
		for( y=1; y<height-1; y++ )
		{
			uchar* image_ptr = data1 + y * widthStep1;
			uchar* output_ptr = data2+ y * widthStep2;
			for( x=1; x<widthStep1-1; x++ )
			{

				int sobel= abs(neighbor(image_ptr,x,-1,-1,widthStep1,nch) -  neighbor(image_ptr,x,1,-1,widthStep1,nch) +
					2*neighbor(image_ptr,x,-1,0,widthStep1,nch) - 2*neighbor(image_ptr,x,1,0,widthStep1,nch) +
					neighbor(image_ptr,x,-1,1,widthStep1,nch) -   neighbor(image_ptr,x,1,1,widthStep1,nch)
					);

				sobel+=abs(neighbor(image_ptr,x,-1,-1,widthStep1,nch) -  neighbor(image_ptr,x,-1,1,widthStep1,nch) +
					2*neighbor(image_ptr,x,0,-1,widthStep1,nch) - 2*neighbor(image_ptr,x,0,1,widthStep1,nch) +
					neighbor(image_ptr,x,1,-1,widthStep1,nch) -   neighbor(image_ptr,x,1,1,widthStep1,nch)
					);

				output_ptr[x] = sobel > 255 ? 255 : sobel;;          
			}
		} 
	
	}

}

uchar Sobel::neighbor(uchar *data, int i, int dx, int dy, int step, int nch)
{
	return *(data+dy*step+i+dx*nch);
}